package net.pulseproject.commons.midi.mediator;

import javax.sound.midi.Receiver;
import javax.sound.midi.ShortMessage;

import net.pulseproject.commons.midi.MessageAnalyzer;
import net.pulseproject.commons.midi.Transmitable;
import net.pulseproject.commons.midi.entity.MidiSocket;
import net.pulseproject.commons.misc.collection.Enableable;
import net.pulseproject.commons.util.MidiUtil;
import net.pulseproject.router.modules.misc.MidiReceiverModuleListener;
import net.pulseproject.router.modules.useable.MidiReceiverModule;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Former name: ReroutingMidiReceiverModuleListener
 */
class ReroutingListener implements MidiReceiverModuleListener, Enableable {
	
	private static final Log LOG = LogFactory.getLog(ReroutingListener.class);
	
	private final Receiver openedMidiReceiver;
	
	private final MidiSocket socket;
	
	private final MessageAnalyzer analyzer;
	
	private boolean enabled = true;
	
	
	public ReroutingListener(final Receiver openedMidiReceiver,
							 final MidiSocket socket,
							 final MessageAnalyzer analyzer) {
		if(openedMidiReceiver == null) { throw new IllegalArgumentException("openedMidiReceiver == null"); }
		this.openedMidiReceiver = openedMidiReceiver;
		
		if(socket == null) { throw new IllegalArgumentException("socket == null"); }
		this.socket = socket;
		
		if(analyzer == null) { throw new IllegalArgumentException("analyzer == null"); }
		this.analyzer = analyzer;
	}
	
	@Override
	public final void onMessageReceived(final ShortMessage message,
										final Transmitable transmitable,
										final MidiReceiverModule receiver) {
		LOG.debug("onMessageReceived(message=" + MidiUtil.toString(message) + ", transmitable, receiver)");
		
		if(this.enabled == false) {
			LOG.debug("onMessageReceived(..) ... not sending MIDI message as receiver is disabled.");
			return;
		}
		
		final ShortMessage newMessage;
		if(this.analyzer.isControllerMessage(message) == true) {
			newMessage = MidiUtil.deriveMessageByChannelAndData1(message, this.socket.getChannel().intValue(),
					this.socket.getController().intValue());
		} else {
			newMessage = MidiUtil.deriveMessageByChannel(message, this.socket.getChannel().intValue());
		}
		
		LOG.debug("  ... going to send message " + MidiUtil.toString(newMessage) + " to real MIDI system.");
		// this is where the actual magic happens, and data is sent to the MIDI system
		this.openedMidiReceiver.send(newMessage, 0);
	}

	@Override
	public final boolean isEnabled() {
		return this.enabled;
	}

	@Override
	public final void setEnabled(final boolean enabled) {
		LOG.trace("setEnabled(enabled=" + enabled + ") old value: " + this.enabled + "; " +
				"for this.socket: " + this.socket);
		this.enabled = enabled;
	}
	
	@Override
	public final String toString() {
		return "ReroutingListener[socket=" + this.socket + "]";
	}
}
